<!-- Author: Edwin -->
<template>
  <div class="bot-design-page-all"
       style="position:relative;"
       v-loading='pageLoading'>
    <div v-if="botInfo.tenantCode !== $store.state.user.tenantCode" class="no-permission">
      <span v-if="botInfo.tenantCode">You don't have permission yet.</span>
      <span v-else>No data, please refresh and try again.</span>
    </div>
    <div class="action"
         :class="designModePression ? '' : 'hide-block'">
      <div class="search-area">
        <div class="title">Blocks</div>
        <!-- <el-input size="mini"
                  placeholder="Search Block">
          <el-button slot="append"
                     icon="el-icon-search"></el-button>
        </el-input> -->
      </div>
      <div class="block-list">
        <el-tabs v-model="blockType"
                 :before-leave='onchangeTabs'>
          <el-tab-pane v-for="(scriptTypeItem,itemIndex) in comScriptTypeList"
                       :key="itemIndex"
                       :label="scriptTypeItem.dictLabel"
                       :name="scriptTypeItem.dictValue">
            <div v-if='blocksList.length > 0'
                 class="card-content scroll-css">
              <BlockItem v-for="(item, i) in designMode === 'designTemplate' ? blocksList : getBlockListForType(scriptTypeItem.dictValue)"
                         :key="i"
                         :blockInfo='item' />
            </div>
            <div v-else
                 class="card-content-nodata">No Data&nbsp;&nbsp;
              <el-button @click="getBlocksList"
                         type="text"
                         size="mini">Refresh</el-button>
            </div>
          </el-tab-pane>
        </el-tabs>

      </div>
    </div>
    <div class="content"
         :class="designMode === 'designTemplate' ? '' : 'width100'">
      <div class="header">
        <div class="header-name">
          <img :src="botInfo.icon?botInfo.icon:defaultImgUrl"
               alt="">
          <span> {{ botInfo.name }}</span>
        </div>
        <!-- <el-button-group> -->
        <div>
          <el-button v-if="designMode === 'designTemplate'||$hasPermission('sys:bots:design:custom')"
                     @click="deleteAllBlocks"
                     size="mini"
                     type="danger">{{$t('custom.bots.clearbtn')}}</el-button>
          <el-button v-if="$hasPermission('sys:bots:edit')"
                     @click="editBots"
                     size="mini"
                     type="primary">{{$t('custom.bots.editbtn')}}</el-button>
          <el-button v-if="$hasPermission('sys:bots:delete')"
                     @click="deleteBots"
                     size="mini"
                     type="danger">{{$t('custom.bots.deletebtn')}}</el-button>
          <el-button v-if="$hasPermission('sys:bots:design')"
                     @click="resetBot"
                     size="mini"
                     type="primary">{{$t('custom.bots.resetbtn')}}</el-button>
          <!-- <el-button v-if="$hasPermission('sys:bots:design:push')"
                     @click="publishBot"
                     size="mini"
                     type="warning">{{$t('custom.dataset.publishbtn')}}</el-button> -->
          <el-button v-if="$hasPermission('sys:bots:design')"
                     @click="confirmFlowy(false)"

                     size="mini"
                     type="primary">{{$t('custom.bots.savebtn')}}</el-button>
          <el-button v-if="needCloseBtn"
                     @click="closeComponent"
                     size="mini"
                     type="primary">{{$t('custom.bots.closedbtn')}}</el-button>
        </div>
        <!-- </el-button-group> -->
      </div>
      <div ref="canvas"
           id="canvas"
           class="scroll-css canvas"></div>
    </div>
    <SettingModel ref="setting-model" />
    <AddUpdate ref="addUpdateForm" @refreshList="init"
      :botType="botType"
       @reselectTemplate="reselectTemplateFn"
      :parentStateObj="botTem"
      ></AddUpdate>
    <SelectBotTemplate ref="addUpdateObjTem"
               @showDataForm="jumpDataForm"></SelectBotTemplate>
    <PublishBot ref="publish-bot" />
  </div>
</template>

<script>
import { flowy } from './flowy'
import BlockItem from './components/block-item'
import { getUUID } from '@/utils'
import SettingModel from './components/setting-model'
import AddUpdate from '../my-bots/add-or-update-bak'
import SelectBotTemplate from '../my-bots/select-bot-tempalte'
import { currentTabRemoveHandle } from '@/utils/common'
import { LinkComponent } from '../my-bots/BotFormatComponents/LinkComponent.js'
import PublishBot from '../bot-template/publish-bot'
import { deleteBotInfoApi } from '@/api/new'

export default {
  props: {
    botIds: {
      type: String,
      default: ''
    },
    needCloseBtn: {
      type: Boolean,
      default: false
    }
  },
  components: { BlockItem, SettingModel, AddUpdate, SelectBotTemplate, PublishBot },
  provide () {
    return {
      scriptList: () => this.blocksList
    }
  },
  data () {
    return {
      botId: '',
      onlyOne: false,
      botTem: -1,
      botType: '',
      botCreated: '',
      blockType: null,
      blocksList: [],
      botInfo: {},
      pageLoading: false,
      recordBotChangeId: '',
      designMode: 'edit',
      settingModelSwitch: false,
      defaultImgUrl: this.$ossLink + '/app/bot/bot-icon-normal.png'
    }
  },
  computed: {
    designModePression () {
      if (this.botInfo.tenantCode === this.$store.state.user.tenantCode) {
        if (this.$hasPermission('sys:bots:design:custom')) {
          if (this.designMode === 'designTemplate') {
            return true
          }
          return true
        } else {
          return false
        }
      } else {
        return false
      }
    },
    triggerBlocksList () {
      return this.blocksList.filter(e => e.type === 'trigger')
    },
    actionBlocksList () {
      return this.blocksList.filter(e => e.type === 'action')
    },
    loggerBlocksList () {
      return this.blocksList.filter(e => e.type === 'logger')
    },
    comScriptTypeList () {
      let tempList = [
        // { dictLabel: 'Trigger', dictValue: 'trigger' },
        { dictLabel: 'Action', dictValue: 'action' },
        { dictLabel: 'Filter', dictValue: 'filter' }
      ]
      try {
        return window.SITE_CONFIG['dictList'].find(e => e.dictType === 'script_type').dataList || tempList
      } catch (error) {
        return tempList
      }
    }
  },
  created () {
    this.botId = this.botIds
    this.botCreated = 'first'
    this.recordBotChangeId = this.botId
    this.observerViewAfterAdding()
  },
  destroyed () {
    this.clearPage()
    this.$root.eventBus.$off('bus')
  },
  watch: {
    'botIds': function (val) {
      this.botId = val
    }
  },
  methods: {
    observerViewAfterAdding () {
      this.$root.eventBus.$on('bus', () => {
        this.confirmFlowy(true)
      })
    },
    init () {
      this.$nextTick(() => {
        const spacingX = 40
        const spacingY = 60
        flowy(this.$refs['canvas'], onGrab, onRelease, onSnap, onRearrange, spacingX, spacingY)
        let _self = this

        function onGrab (block) {
          // When the user grabs a block
        }
        function onRelease (e) {
          // When the user releases a block
          _self.$nextTick(() => {
            !_self.hasFirstBlock() && _self.initAttribute(e)
          })
        }
        function onSnap (block, first, parent) {
          // When a block snaps with another one
          _self.initAttribute(block)
          return true
        }
        function onRearrange (block, parent) {
          // When a block is rearranged
          return true
        }
        if (this.botId) {
          this.getBotInfo()
          this.getBlocksList()
        } else {
          this.$message.warning('Bot ID is nonentity.')
          this.clearPage()
        }
      })
    },
    reselectTemplateFn () {
      this.$nextTick(() => {
        this.$refs.addUpdateForm.visible = false
        this.$refs.addUpdateObjTem.visible = true
        this.$refs.addUpdateObjTem.init()
      })
    },
    publishBot () {
      this.$refs['publish-bot'].openDialog(this.botInfo.id)
    },
    jumpDataForm (item) {
      this.$refs.addUpdateForm.visible = true
      this.$nextTick(() => {
        // this.$refs.addUpdateForm.dataForm.id = this.botInfo.id
        // this.$refs.addUpdateForm.init()
      })
      this.botTem = item.item
      this.botType = item.type
    },
    getBlockListForType (type) {
      return this.blocksList.filter(e => e.type === type)
    },
    clearPage () {
      this.blockType = null
      this.blocksList = []
      this.botInfo = {}
      // flowy.deleteBlocks()
      try {
        flowy.clearWay()
      } catch (error) { }
    },
    getBlocksList () {
      this.$interface.bots.getScriptListApi({ tenantId: this.$store.state.user.tenantCode })
        .then(({ data: res }) => {
          if (res.code !== 0) {
            return this.$message.error(res.msg)
          }
          this.blocksList = res.data
          this.scriptList = this.blocksList
        }).catch(() => { })
    },
    getBotInfo () {
      this.pageLoading = true
      this.$interface.botStore.getTenantBotInfoApi({ id: this.botId })
        .then(({ data: res }) => {
          this.pageLoading = false
          if (res.code !== 0) {
            return this.$message.error(res.msg)
          }
          this.botInfo = res.data
          this.$store.state.bot.businessType = res.data.businessType
          this.importFlowy() // reset page
          this.setOriginData(res.data)
          this.$store.state.bot.isShow = true
          if (this.$hasPermission('sys:bots:design:custom') && this.botInfo.tenantCode === this.$store.state.user.tenantCode) flowy.addWay()
          if (this.botInfo.tenantCode !== this.$store.state.user.tenantCode && this.botInfo.businessType === 'Custom') {
            this.$store.state.bot.isShow = false
          }
          this.$store.commit('BOTCONTENTCHANGE', false)
          this.$store.commit('BOTFORMFLAG', false)
        })
        .catch(() => {
          this.pageLoading = false
          this.$store.commit('BOTCONTENTCHANGE', false)
          this.$store.commit('BOTFORMFLAG', false)
        })
    },
    setOriginData (data) {
      try {
        let originType = data.sysBotScriptList[0].paramsValue['radioSelect']['radioType']
        let originId = data.sysBotScriptList[0].paramsValue['radioSelect']['selectId']
        this.$store.dispatch('triggerSelectDataIType', originType)
        this.$store.dispatch('triggerSelectDataId', originId)
      } catch (error) { }
    },
    updateBotInfo (params, isDelete) {
      if (this.pageLoading) return
      this.pageLoading = true
      this.$interface.botStore.putBotUpdateScriptApi(this.botId, params)
        .then(({ data: res }) => {
          this.pageLoading = false
          if (res.code !== 0) {
            return this.$message.error(res.msg)
          }
          this.$store.commit('BOTFORMFLAG', false)
          this.$store.commit('BOTCONTENTCHANGE', false)
          this.settingModelSwitch = true
          this.$message.success(res.msg)
          if (!isDelete) {
            this.getBotInfo()
          }
          if (isDelete) {
            this.$root.eventBus.$emit('delete')
          }
        })
        .catch(() => {
          this.pageLoading = false
        })
    },
    getSysBotScriptList () {
      let flowSetting = flowy.output()
      let tempList = []
      if (flowSetting) {
        let blocks = flowSetting.blocks
        const getTriggerId = parentId => {
          try {
            return getAttributeValue(blocks.find(e => e.id === parentId).attr, 'trackid')
          } catch (error) {
            return null
          }
        }
        const getBlockInfo = attr => {
          try {
            return JSON.parse(attr.find(e => Boolean(e.blockinfo) === true).blockinfo)
          } catch (error) {
            return null
          }
        }
        const getAttributeValue = (attr, key) => {
          try {
            let tempData = null
            switch (key) {
              case 'paramsvaluesend':
                tempData = JSON.parse(attr.find(e => Boolean(e[key]) === true)[key])
                break
              case 'trackid':
                tempData = attr.find(e => Boolean(e[key]) === true)[key]
                break
              default:
                break
            }
            return tempData
          } catch (error) {
            return null
          }
        }
        for (let i = 0; i < blocks.length; i++) {
          const item = blocks[i]
          const blockInfo = getBlockInfo(item.attr)
          tempList.push({
            botId: this.botId,
            scriptId: blockInfo.id,
            triggerId: item.parent < 0 ? this.botId : getTriggerId(item.parent),
            paramsValue: getAttributeValue(item.attr, 'paramsvaluesend') ? getAttributeValue(item.attr, 'paramsvaluesend') : blockInfo.paramsValue,
            trackId: getAttributeValue(item.attr, 'trackid')
          })
        }
      }
      return tempList
    },
    getTriggerType () {
      let flowSetting = flowy.output()
      let triggerType = null
      if (flowSetting) {
        let blocks = flowSetting.blocks
        const getParamsvaluesend = attr => {
          try {
            return JSON.parse(attr.find(e => Boolean(e.paramsvaluesend) === true).paramsvaluesend)
          } catch (error) {
            return null
          }
        }
        if (blocks && blocks.length && blocks.length > 0) {
          try {
            let selectRadio = getParamsvaluesend(blocks[0].attr).radioSelect.radioType
            switch (selectRadio) {
              case 'dataset':
                triggerType = 'Timed'
                break
              case 'widget':
                triggerType = 'Timed'
                break
              default:
                triggerType = this.botInfo.triggerType
                break
            }
          } catch (error) {
            triggerType = this.botInfo.triggerType
          }
        }
      }
      return triggerType
    },
    hasFirstBlock () {
      try {
        let flowSetting = flowy.output()
        if (flowSetting.blocks && flowSetting.blocks.length && flowSetting.blocks.length > 0) {
          return true
        } else {
          return false
        }
      } catch (error) {
        return false
      }
    },
    onlyHasOneBlock () {
      if (Array.isArray(this.blocksList) && this.blocksList.length === 0) {
        setTimeout(() => {
          this.onlyHasOneBlock()
        }, 300)
        return false
      }
      let flowSetting = flowy.output()
      try {
        if (flowSetting.blocks && flowSetting.blocks.length && flowSetting.blocks.length === 1) {
          this.onlyOne = true
        } else {
          this.onlyOne = false
        }
      } catch (error) {
        this.onlyOne = false
      }
      if (this.onlyOne) {
        let elementInfo = JSON.parse(flowSetting.blocks[0].attr.find(e => Boolean(e.blockinfo) === true).blockinfo)
        let element = document.querySelector(".blockid[value='" + 0 + "']").parentNode
        if (!this.settingModelSwitch) {
          this.settingModelSwitch = false
          if (this.designModePression) this.$refs[`setting-model`].open(elementInfo, element)
        }
      }
      if (!flowSetting) {
        flowy.deleteBlocks()
      }
    },
    deleteAllBlocks () {
      flowy.deleteBlocks()
    },
    confirmFlowy (isDelete) {
      if (!this.botId) {
        return this.$message.error('Please try again and after reload.')
      }
      if (!this.hasFirstBlock()) {
        return this.$message.error('Please drag block for bot.')
      }
      const params = {
        ...this.botInfo,
        flowSetting: flowy.output(),
        sysBotScriptList: this.getSysBotScriptList(),
        triggerType: this.getTriggerType()
      }
      this.updateBotInfo(params, isDelete)
    },
    importFlowy (action) {
      let temp = this.botInfo.flowSetting
      if (temp) {
        flowy.deleteBlocks()
        flowy.import(temp)
      }
      if (action !== 'reset') {
        this.initBlockTabs()
        this.onlyHasOneBlock()
      }
    },
    initBlockTabs () {
      this.blockType = this.comScriptTypeList[0].dictValue
    },
    initAttribute (e) {
      // paramsValueSend
      this.$store.commit('BOTCONTENTCHANGE', true)
      if (!e || e.getAttribute('paramsValueSend')) {
        return false
      }
      let itemJson = JSON.parse(e.getAttribute('blockInfo')).paramsJson.fields
      e.setAttribute('paramsValueSend', JSON.stringify(this.getBlockItemDefaultDataForm(itemJson)))
      // trackId
      e.setAttribute('trackId', getUUID())
    },
    getBlockItemDefaultDataForm (itemJson) {
      if (!Array.isArray(itemJson)) {
        return {}
      }
      let temp = {}
      for (let i = 0; i < itemJson.length; i++) {
        const element = itemJson[i]
        if (typeof element.defaultValue === 'object') {
          temp[element.text] = JSON.parse(JSON.stringify(element.defaultValue))
        } else {
          temp[element.text] = element.defaultValue
        }
      }
      return temp
    },
    onchangeTabs (val, oldVal) {
      // try {
      //   if (val === this.comScriptTypeList[0].dictValue && this.hasFirstBlock()) {
      //     return false
      //   }
      //   if ((val === this.comScriptTypeList[1].dictValue || val === this.comScriptTypeList[2].dictValue) && !this.hasFirstBlock()) {
      //     return false
      //   }
      // } catch (error) { }
    },
    closeComponent () {
      this.$emit('closeComponent')
    },
    resetBot () {
      this.$confirm(this.$t('custom.resetTips'), this.$t('prompt.title'), {
        confirmButtonText: this.$t('custom.continue'),
        cancelButtonText: this.$t('cancel'),
        type: 'danger'
      })
        .then(() => {
          this.$store.commit('BOTCONTENTCHANGE', false)
          this.$store.commit('BOTFORMFLAG', false)
          this.importFlowy('reset')
        })
        .catch(() => { })
    },
    editBots () {
      this.$nextTick(() => {
        this.$store.commit('BOTFORMEDIT', true)
        this.$refs.addUpdateForm.dataForm.id = this.botInfo.id
        this.$refs.addUpdateForm.init()
      })
    },
    deleteBots () {
      this.$confirm(this.$t('prompt.info', { 'handle': this.$t('delete') }), this.$t('prompt.title'), {
        confirmButtonText: this.$t('confirm'),
        cancelButtonText: this.$t('cancel'),
        type: 'warning'
      }).then(() => {
        const params = {
          id: this.botInfo.id
        }
        deleteBotInfoApi(params).then(({ data: res }) => {
          if (res.code !== 0) {
            return this.$message.error(res.msg)
          }

          let detailIndex = this.$store.state.contentTabs.findIndex(e => e.title === 'Bot Detail')
          if (detailIndex > -1) {
            if (this.$store.state.contentTabs[detailIndex].query.botId === this.botInfo.id) {
              currentTabRemoveHandle(this.$store.state.contentTabs[detailIndex].name)
            }
          }
          currentTabRemoveHandle(this.$store.state.contentTabsActiveName)
          LinkComponent.$emit('initPageList')
          return this.$message.success(res.msg)
        })
      }).catch(() => {
      })
    },
    activatedInit () {
      if (this.$route.query.designMode) this.designMode = this.$route.query.designMode
      else this.designMode = 'edit'
      let refreshStatus = false
      if (this.$store.state.bot.botId && this.$store.state.bot.botId === this.recordBotChangeId) {
        refreshStatus = false
      } else if (this.$store.state.bot.botId && this.$store.state.bot.botId !== this.recordBotChangeId) {
        this.recordBotChangeId = this.$store.state.bot.botId
        this.botId = this.$store.state.bot.botId
        refreshStatus = true
      }
      if (!this.botCreated && refreshStatus) {
        this.init()
      }
    }
  },
  activated () {
    this.activatedInit()
  },
  deactivated () {
    this.botCreated = ''
  }
}
</script>

<style lang='scss'>
@import "./bot-design.scss";
@import "./components/bot.scss";
</style>
<style lang="scss" scoped>
.hide-block {
  overflow: hidden;
  width: 0 !important;
  height: 0 !important;
}
.width100 {
  width: 100% !important;
}
.no-permission {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #999;
  font-size: 3em;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 2;
  background: #fff;
}
</style>
